﻿using System.Collections.Generic;
#if NETFX_CORE
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
#else
using System.Windows;
using System.Windows.Media;
#endif

namespace FreshMeat.Xaml
{
   public static class VisualTreeEnumerator
   {
      /// <summary>
      /// Enumerates a tree using a breadth-first approach starting at the specified item.
      /// </summary>
      public static IEnumerable<DependencyObject> EnumerateBreadthFirst(DependencyObject startingItem)
      {
         for (var i = 0; i < VisualTreeHelper.GetChildrenCount(startingItem); i++)
            yield return VisualTreeHelper.GetChild(startingItem, i);

         for (var i = 0; i < VisualTreeHelper.GetChildrenCount(startingItem); i++)
         {
            var child = VisualTreeHelper.GetChild(startingItem, i);
            foreach (var grandChild in EnumerateBreadthFirst(child))
               yield return grandChild;
         }
      }

      /// <summary>
      /// Enumerates a tree using a depth-first approach starting at the specified item.
      /// </summary>
      public static IEnumerable<DependencyObject> EnumerateDepthFirst(DependencyObject startingItem)
      {
         for (var i = 0; i < VisualTreeHelper.GetChildrenCount(startingItem); i++)
         {
            var child = VisualTreeHelper.GetChild(startingItem, i);
            yield return child;

            foreach (var grandChild in EnumerateDepthFirst(child))
               yield return grandChild;
         }
      }

      /// <summary>
      /// Enumerates items going up the visual tree, stopping either at the root or the specified object.
      /// </summary>
      /// <param name="start">Object to start at.</param>
      /// <param name="stop">Optional object to stop at.</param>
      public static IEnumerable<DependencyObject> EnumerateUp(DependencyObject start, DependencyObject stop = null)
      {
         var current = start;
         do
         {
            yield return current;

            if (current == stop)
               break;

            current = VisualTreeHelper.GetParent(current);
         } while (current != null && current != stop);
      }
   }
}
